package query;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Comparator;

import net.sf.jclec.IConfigure;
import net.sf.jclec.IFitness;
import net.sf.jclec.IIndividual;
import net.sf.jclec.base.AbstractEvaluator;
import net.sf.jclec.fitness.SimpleValueFitness;
import net.sf.jclec.fitness.ValueFitnessComparator;
import net.sf.jclec.intarray.*;


import org.apache.commons.configuration.Configuration;

/**
 * TSP optimization problem
 * 
 * @author Alberto Cano
 * @author Jose Maria Luna
 * @author Juan Luis Olmo
 * @author Amelia Zafra
 * @author Sebastian Ventura
 */

public class SpanF extends AbstractEvaluator implements IConfigure
{
	/////////////////////////////////////////////////////////////////
	// --------------------------------------- Serialization constant
	/////////////////////////////////////////////////////////////////
	
	/** Generated by Eclipse */
	
	private static final long serialVersionUID = -2635335580011827514L;
	
	/////////////////////////////////////////////////////////////////
	// --------------------------------------------------- Properties
	/////////////////////////////////////////////////////////////////
	
	/** Maximize of minimize functions? */
	
	protected boolean maximize = true;
	
	/** Distances matrix */
	
	private double distances[][];
	
	/////////////////////////////////////////////////////////////////
	// ---------------------------------------------- Class variables
	/////////////////////////////////////////////////////////////////
	
	private Comparator<IFitness> COMPARATOR;

	private BufferedReader br;
	
	/////////////////////////////////////////////////////////////////
	// ------------------------------------------------- Constructors
	/////////////////////////////////////////////////////////////////
	/**
	* Empty constructor.
	*/
	public SpanF()
	{
		super();
	}
	
	/////////////////////////////////////////////////////////////////
	// ------------------------------- Setting and getting properties
	/////////////////////////////////////////////////////////////////
	
	/** Is this evaluator being used to maximize a function?
	* @return true if evaluator is used to maximize function, false
	otherwise. */
	public boolean isMaximize()
	{
		return maximize;
	}
	
	/** Set the maximize flag.
	* @param maximize Actual maximize flag. */
	public void setMaximize(boolean maximize)
	{
		this.maximize = maximize;
	}
	
	/////////////////////////////////////////////////////////////////
	// ------------------------ Overwriting AbstractEvaluator methods
	/////////////////////////////////////////////////////////////////
	
	
	protected void evaluate(IIndividual ind)
	{	
		// Individual genotype
		int [] genotype = ((IntArrayIndividual)ind).getGenotype();
		
		double distance = 0;
		
		for (int i=0; i<genotype.length; i++) 
			
			distance +=genotype[i];
		//	distance += distances[genotype[i]][genotype[i+1]];
	
	//	distance += distances[genotype[genotype.length-1]][genotype[0]];
		
		ind.setFitness(new SimpleValueFitness(distance));
	}
	
	public void configure(Configuration settings)
	{		
		String fileName = settings.getString("[@file-name]");
		String line = null;
		int numberCities = settings.getInt("[@number-cities]"), i=0;
		File file = new File (fileName);
		distances = new double[numberCities][numberCities];
		double x[]= new double [numberCities];
        double y[]= new double [numberCities];
		
	    try {
			FileReader fr = new FileReader(file);
			br = new BufferedReader(fr);
			
	        while(!(line=br.readLine()).contains("NODE_COORD_SECTION"));
	        while(!(line=br.readLine()).contains("EOF"))
	        {
	        	line=String.copyValueOf(line.toCharArray(), line.indexOf(" "), line.length()-line.indexOf(" "));
	        	line=line.trim();
	        	x[i]=Double.valueOf(line.split(" ")[0]).doubleValue();
	        	line=String.copyValueOf(line.toCharArray(), line.indexOf(" "), line.length()-line.indexOf(" "));
	        	line=line.trim();
	        	y[i]=Double.valueOf(line.split(" ")[0]).doubleValue();
	        	i++;
	        }
	        
	        for(i=0;i<numberCities;i++)
	        	for(int j=i+1;j<numberCities-1;j++)
	        	{
	        		distances[i][j]=Math.sqrt(Math.pow(x[i]-x[j],2)+Math.pow(y[i]-y[j],2));
	        		distances[j][i]=distances[i][j];
	        	}
	        
		} catch (IOException e) {
            System.out.println(e);
		}
	}
	
	/////////////////////////////////////////////////////////////////
	// ---------------------------- Implementing IEvaluator interface
	/////////////////////////////////////////////////////////////////
	
	/**
	 * {@inheritDoc}
	 */
	
	public Comparator<IFitness> getComparator()
	{
		// Set fitness comparator (if necessary)
		if (COMPARATOR == null)
			COMPARATOR = new ValueFitnessComparator(!maximize);
	
		// Return comparator
		return COMPARATOR;
	}
}